markovifyRThanks to Maëlle Salmon, who referred me to this post by Julia Silge and Nick Larsen, I explored doing this using the markovifyR package, and the results are unbelievable. See the bottom of the post for an updated batch of sonnets!
I recently saw Katie Jolly’s post, in which she produced Rupi Kuar-style poems using Markov Chains in R. I absolutely loved it, so I decided to try it with Shakespeare’s 154 sonnets using her post as a skeleton.
In addition to markovchain and tidyverse, I’m going to use the gutenberger package to download the sonnets.
library(gutenbergr)
library(tidyverse)
library(markovchain)
shakespeare <- gutenberg_works(title == "Shakespeare's Sonnets") %>%
pull(gutenberg_id) %>%
gutenberg_download(verbose = FALSE)
shakespeare
## # A tibble: 2,625 x 2
## gutenberg_id text
## <int> <chr>
## 1 1041 THE SONNETS
## 2 1041 ""
## 3 1041 by William Shakespeare
## 4 1041 ""
## 5 1041 ""
## 6 1041 ""
## 7 1041 ""
## 8 1041 " I"
## 9 1041 ""
## 10 1041 " From fairest creatures we desire increase,"
## # ... with 2,615 more rows
Because the sonnets are in gutenberger, they’re already in a nice format to work with. I just need to do a little cleaning up: like Katie, I removed the punctuation, but I also have to clear out the sonnet titles, which were Roman numerals, and some title info.
# a little function to make life easier
`%not_in%` <- function(lhs, rhs) {
!(lhs %in% rhs)
}
# remove new lines symbol, sonnet Roman numerals, and punctation
# and split into vector
bills_words <- shakespeare %>%
mutate(text = text %>%
str_trim() %>%
str_replace_all("--", " ") %>%
str_replace_all("[^[:alnum:][:space:]']", "") %>%
str_replace_all("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",
"") %>%
str_to_lower()) %>%
filter(text %not_in% c("the sonnets", "by william shakespeare", "", " ")) %>%
pull(text) %>%
str_split(" ") %>%
unlist()
I’m also going to extract the punctuation and assess how many of each there are for when I actually assemble the sonnets later.
punctuation <- shakespeare %>%
pull(text) %>%
str_extract_all("[^[:alnum:][:space:]']") %>%
unlist()
punctuation_probs <- punctuation[punctuation %not_in% c("-", "(", ")")] %>%
table() %>%
prop.table()
Now fit the Markov Chain with the vector of words.
# fit a Markov Chain
sonnet_chain <- markovchainFit(bills_words)
cat(markovchainSequence(n = 10, markovchain = sonnet_chain$estimate), collapse = " ")
doubting the mortal moon hath her husband’s shape so proud
And finally, here are a few functions to piece together lines to make them look like a sonnet using the walk() function from purrr to print out the lines (since it’s a side effect). No, they’re not actually iambic pentameter :(
write_a_line <- function(n_lines = 1) {
walk(1:n_lines, function(.x) {
# put together lines of more or less average length
lines <- markovchainSequence(n = sample(c(6:9), 1),
markovchain = sonnet_chain$estimate) %>%
paste(collapse = " ")
# add end-of-line punctuation based on their occurence
end_punctuation <- ifelse(.x == n_lines, ".",
sample(names(punctuation_probs),
size = 1,
prob = punctuation_probs))
cat(paste0(lines, end_punctuation, " \n"))
})
}
psuedosonnet <- function() {
walk(1:3, function(.x) {
write_a_line(4)
cat(" \n")
})
write_a_line(2)
}
Let’s try it out.
set.seed(154)
psuedosonnet()
which physic did i toil all too grossly,
of happy you nor falls under the master;
o absence seem’d it fears no form form,
you would i break of the darling buds of.
of brass are my head where our fashion an,
stars of thy book of small glory to swear,
what wealth some child of the painter must die.
the fierce thing replete with that bears it.
seems your feature incapable of such seems seeing for,
in his spoil of trust and,
blood make me soon to thy days are bright,
in your worth held and i swear to wait.
beauty tempting her poor retention could with a,
and the treasure of may be.
psuedosonnet()
my spirit a separable spite take;
it then say so flatter the sessions of,
pen hearing you drink potions of one?
and more hath all art for.
that best acquainted with kings when thou,
where breath but their proud compare thou,
of mouthed graves will grind on thy,
fleece made and thy cheek and this.
and when that is so for’t lies where all,
so is this say that we?
against myself i read self the earth remov’d lord?
mother for now than spurring to please him.
and all determinate for thee in grecian tires are,
and eyes can see till the general evil still.
psuedosonnet()
debt and from accident it may!
shine bright in hope what he doth deceive,
their brave state with tears thou in whose,
muse doth well knows is crown’d crooked knife.
nor white when my body is more then her:
look in my oblation poor infant’s discontent,
sail to his memory but all the other,
the least yet like none lov’st thou.
creature the prey of words by adding one and:
esteem’d when it ten for i have,
bosoms fits but then how shall beauty and leap’d,
my pen hearing you will give them for what.
end doth ride with fulness tomorrow;
methinks i slept in thy trespass with.
psuedosonnet()
a dearer birth to divide the lovely,
lips and beauty lack of worms to die but,
and do i be belov’d of praise.
sail doth use is famish’d for.
by praising him but if this shalt find out,
sweet that i read self resemble creating,
grace you look upon the most which,
make sweet love put beside his beauty of your.
pen reserve their glory but these quicker elements,
be as thou that then thou art my love!
by the store to flow for his,
of thee but mend to the marigold at the.
time you doth live look for.
want nothing sweet self away and therefore.
psuedosonnet()
wh’r better angel in some in,
oaths of good turns to death my comfort,
directed then gentle gait making thus with.
of conscience hold in his spring.
like a zealous pilgrimage to my heart,
politic that through the joy behind,
proud livery so fast as high to set and,
could write of shame commits for her pleasure lost.
sweetest odours made for love when thou canst not.
featureless and there is impannelled a,
exceeded by our time thou shalt hap to wonder,
grief though rosy lips and heart wound.
thou repent yet do thy parts do our!
death do show it is daily new to.
Alright, this time I’m going to try it with the markovifyR package. I’m basically going to do the same cleaning as above, but this time I’ll be putting entire sentences, punctuation and all, into the Markov model. The markovify_text() function also accepts start words, so I thought it might look good to start with a sample of 100 starting words from the sonnets and construct the lines from there.
library(markovifyR)
# same as above, but maintain as sentences and keep punctuation
bills_sentences <- shakespeare %>%
mutate(text = text %>%
str_trim() %>%
str_replace_all("--", " ") %>%
str_replace_all("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",
"") %>%
str_to_lower()) %>%
filter(text %not_in% c("the sonnets", "by william shakespeare", "", " "))
# fit the Markov Chain
markovify_model <-
generate_markovify_model(
input_text = bills_sentences$text,
markov_state_size = 2L,
max_overlap_total = 25,
max_overlap_ratio = .85
)
# generate a sonnet
markovify_sonnet <- function() {
lines <- markovify_text(
markov_model = markovify_model,
maximum_sentence_length = 75,
output_column_name = 'sonnet_line',
count = 50,
tries = 1000,
start_words = sample(generate_start_words(markovify_model)$wordStart, 100),
only_distinct = TRUE,
return_message = FALSE) %>%
filter(str_count(sonnet_line, "\\w+") > 5 & str_count(sonnet_line, "\\w+") < 10) %>%
slice(sample(1:n(), 14)) %>%
mutate(id = 1:n()) %>%
select(id, sonnet_line)
# add a period to the last line if the last charachter isn't punctuation
# that ends a sentence
last_line <- lines[lines$id == 14, "sonnet_line"]
lines[lines$id == 14, "sonnet_line"] <- str_replace(last_line,
".$(?<!//.//!//?|[:alnum:])", ".")
# print in a sonnet-like format
walk(1:14, function(.x) {
cat(lines$sonnet_line[.x], " \n")
# add a space every four lines
if (.x %% 4 == 0) cat("\n")
})
}
markovify_sonnet()
unmoved, cold, and to his side;
feeding on that which it doth belong
my bonds in thee are seen
pity me then, dear friend, and i be gone,
my mistress, when she walks, treads on the way,
unmoved, cold, and to be invited
never believe though in my purpose bred,
unmoved, cold, and to his new-appearing sight,
feeds on the kingdom of the thing it was,
lo! thus, by day oppress’d,
two loves i have seen the hungry ocean gain
against that time do i my self almost despising,
no, it was nourish’d by.
feeding on that which flies before her face.
markovify_sonnet()
had, having, and in my nature reign’d,
save, where you may be, or your affairs suppose,
prison my heart mine eye awake:
or whether revolution be the view;
were it not with his presence grace impiety,
stirr’d by a painted beauty to his store;
how like a deceived husband; so love’s face
suffering my friend for my possessing,
resembling strong youth in every thing,
bearing the wanton burden of the thing they see;
hast thou, the master mistress of my true spirit?
better becomes the grey cheeks of the watery main,
pitiful thrivers, in their birth, and where they grew:
thus do i envy those jacks that nimble leap.
markovify_sonnet()
beyond all date; even to thy will,
within the gentle closure of my pity-wanting pain.
when i have frequent been with unknown minds,
thee have i not lock’d up in sheaves,
feeds on the finger of a former sight.
i see barren of new pride,
now, while the world may see my pleasure:
when love, converted from the fierce tiger’s jaws,
wishing me like to the heart;
no bitterness that i have scanted all,
suns of the thing she would have stay;
no bitterness that i honour most.
beshrew that heart that makes my heart is tied?
perforce am thine, and all things rare.
markovify_sonnet()
look in thy abundance am suffic’d,
haply i think my love and thy straying youth,
better becomes the grey cheeks of the sun,
tempteth my better angel from my self depart
with means more blessed than my thoughts canst move,
sweet beauty hath no exchequer now but his,
whilst, like a deceived husband; so love’s face
crowning the present, doubting of the east,
in praise of ladies dead and lovely youth,
o! though i love thee more,
crowning the present, doubting of the dead,
i all alone stands hugely politic,
feeding on that which on thy sport,
hast thou, the master mistress of my heart.
markovify_sonnet()
of mouthed graves will give thee so thine own,
you are so strongly in my verse shall stand.
nor need i not glance aside
mine be thy love more strong,
whereon the stars do i not free.
before the golden tresses of the spring,
counting no old to dress his beauty new;
you are so strongly in my head
ruin hath taught me thus to be cross’d:
in him thy fair imperfect shade
too base of thee to give?
too base of thee this i do but tend,
save where thou dost wake elsewhere,
ay me! but yet be most proud of many.
Well, call me Shockedspeare.
Exit, pursued by a bear